package fuzion24.device.vulnerability.vulnerabilities.framework.media;

import android.content.Context;
import android.util.Log;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.List;

import fuzion24.device.vulnerability.util.CPUArch;
import fuzion24.device.vulnerability.vulnerabilities.VulnerabilityTest;
import fuzion24.device.vulnerability.vulnerabilities.helper.BinaryAssets;
import fuzion24.device.vulnerability.vulnerabilities.helper.KMPMatch;

/**
 * Created by fuzion24 on 12/14/15.
 */
public class CVE_2015_6616  implements VulnerabilityTest {

/*
    CVE	Bug(s) with AOSP links	Severity	Affected versions	Date reported
    CVE-2015-6616
    ANDROID-24630158	Critical	6.0 and below	Google Internal
    ANDROID-23882800	Critical	6.0 and below	Google Internal
    ANDROID-17769851	Critical	5.1 and below	Google Internal
    ANDROID-24441553	Critical	6.0 and below	Sep 22, 2015
    ANDROID-24157524	Critical	6.0	Sep 08, 2015

    ANDROID-24630158 https://android.googlesource.com/platform%2Fframeworks%2Fav/+/257b3bc581bbc65318a4cc2d3c22a07a4429dc1d
    ANDROID-23882800 https://android.googlesource.com/platform%2Fframeworks%2Fav/+/0d35dd2068d6422c3c77fb68f248cbabf3d0b10c
    ANDROID-17769851 https://android.googlesource.com/platform%2Fframeworks%2Fav/+/dedaca6f04ac9f95fabe3b64d44cd1a2050f079e
    ANDROID-24441553 https://android.googlesource.com/platform%2Fframeworks%2Fav/+/5d101298d8b0a78a1dc5bd26dbdada411f4ecd4d
    ANDROID-24157524 https://android.googlesource.com/platform%2Fexternal%2Flibavc/+/2ee0c1bced131ffb06d1b430b08a202cd3a52005
*/

    private static final String TAG = "CVE-2015-6616";

    @Override
    public String getCVEorID() {
        return "CVE-2015-6616";
    }

    @Override
    public boolean isVulnerable(Context context) throws Exception {
        File stagefrightlib = new File("/system/lib/libstagefright.so");
        if(!stagefrightlib.exists() || !stagefrightlib.isFile()){
            throw new Exception("libstagefright.so doesn't exist or is not a file");
        }

        File stagefrightsoftmp4lib = new File("/system/lib/libstagefright_soft_mpeg4dec.so");
        if(!stagefrightsoftmp4lib.exists() || !stagefrightsoftmp4lib.isFile()){
            throw new Exception("libstagefright_soft_mpeg4dec.so doesn't exist or is not a file");
        }


        ByteArrayOutputStream libStageFrightBAOS = new ByteArrayOutputStream((int)stagefrightlib.length());
        BinaryAssets.copy(new FileInputStream(stagefrightlib), libStageFrightBAOS);
        byte[] libstagefrightSO = libStageFrightBAOS.toByteArray();

        KMPMatch binMatcher = new KMPMatch();

        int indexOf = binMatcher.indexOf(libstagefrightSO, "bogus max input size: %zu".getBytes());
        boolean libstagefrightVulnerableToBug17769851 = indexOf == -1;

        indexOf = binMatcher.indexOf(libstagefrightSO, "b/24441553, b/24445122".getBytes());
        boolean libstagefrightVulnerableToBug24441553 = indexOf == -1;

        ByteArrayOutputStream libStageFrightsoftmp4BAOS = new ByteArrayOutputStream((int)stagefrightsoftmp4lib.length());
        BinaryAssets.copy(new FileInputStream(stagefrightsoftmp4lib), libStageFrightsoftmp4BAOS);
        byte[] libstagefrightsoftmp4SO = libStageFrightsoftmp4BAOS.toByteArray();

        indexOf = binMatcher.indexOf(libstagefrightsoftmp4SO, "b/24630158".getBytes());
        boolean libstagefrightVulnerableToBug24630158 = indexOf == -1;

        Log.d(TAG, "libstagefrightVulnerableToBug24630158: " + libstagefrightVulnerableToBug24630158);
        Log.d(TAG, "libstagefrightVulnerableToBug17769851: " + libstagefrightVulnerableToBug17769851);
        Log.d(TAG, "libstagefrightVulnerableToBug24441553: " + libstagefrightVulnerableToBug24441553);


        return libstagefrightVulnerableToBug24630158 ||
                libstagefrightVulnerableToBug17769851 ||
                libstagefrightVulnerableToBug24441553;
    }

    @Override
    public List<CPUArch> getSupportedArchitectures() {
        List<CPUArch> archs = new ArrayList<>();
        archs.add(CPUArch.ALL);
        return archs;
    }
}
